package externalflame.systemdesign.secondkill.service.impl;

import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import externalflame.systemdesign.secondkill.dao.SeckillDao;
import externalflame.systemdesign.secondkill.entity.SecKill;
import externalflame.systemdesign.secondkill.entity.StockInfo;
import externalflame.systemdesign.secondkill.service.SecKillService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service
public class SecKillServiceImpl implements SecKillService {

    @Resource
    RedisTemplate<String, SecKill> redisTemplate;

    @Resource
    SeckillDao seckillDao;

    IdentifierGenerator identifierGenerator = new DefaultIdentifierGenerator();

    private String toRedisKey(Long secKillId) {
        return String.format("secKill:%s", secKillId);
    }

    @Override
    public SecKill get(Long secKillId) {
        // 检查是否可以下单。redis 的检查逻辑不要求特别精准，但是要求可以过滤大部分请求。
        SecKill seckill = redisTemplate.opsForValue().get(toRedisKey(secKillId));
        if (seckill == null) {
            // 查询数据库，补上 Seckill 的数据
            seckill = seckillDao.get(secKillId);
            // 这份儿数据不常改。
            redisTemplate.opsForValue().set(toRedisKey(secKillId), seckill, 1, TimeUnit.DAYS);
        }
        return seckill;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SecKill add(SecKill seckill) {
        Long id = identifierGenerator.nextId(SecKill.class).longValue();
        seckill.setId(id);
        seckillDao.insert(seckill);
        seckillDao.insertStockInfo(identifierGenerator.nextId(StockInfo.class).longValue(), seckill.getProductId(), seckill.getStock(), id);
        seckill = seckillDao.get(id);
        return seckill;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SecKill update(SecKill secKill) {
        Long id = secKill.getId();
        seckillDao.update(secKill);
        redisTemplate.delete(toRedisKey(id));
        return get(id);
    }
}
